#include <iostream>
#include <unistd.h>

#include <libpmemobj++/make_persistent.hpp>
#include <libpmemobj++/p.hpp>
#include <libpmemobj++/persistent_ptr.hpp>
#include <libpmemobj++/pool.hpp>
#include <libpmemobj++/transaction.hpp>
#include <libpmemobj++/container/string.hpp>

struct object {
    pmem::obj::string object_str;
    pmem::obj::p<int> object_int;
    object() {}
    object(const char * str, int num): object_str(str), object_int(num) {};
};

struct root {
	pmem::obj::string root_str;
    pmem::obj::persistent_ptr<object> root_object = nullptr;
};

pmem::obj::persistent_ptr<root> r;

void example_with_ptr(pmem::obj::pool_base &pop) {
	
    std::cout << r->root_str.c_str() << std::endl;
	pmem::obj::transaction::run(pop, [&] {
		r->root_str = "root_string";
	});
	std::cout << r->root_str.c_str() << std::endl;
}

void example_with_object(pmem::obj::pool_base &pop) {
	
    if (r->root_object == nullptr) {
        pmem::obj::transaction::run(pop, [&] {
		    r->root_object = pmem::obj::make_persistent<object>("object_str", 23);
	    });
    }
    std::cout << r->root_object->object_str.c_str() << std::endl;
    std::cout << r->root_object->object_int << std::endl;
}
static int file_exists(char const *file) {
    return access(file, F_OK);
}

int main() {
	pmem::obj::pool<root> pop;
    const char * path = "dst_file";
    if (file_exists(path) != 0) {
        pop = pmem::obj::pool<root>::create(path, "string_example", PMEMOBJ_MIN_POOL);
    } else {
        pop = pmem::obj::pool<root>::open(path, "string_example");
    }
    r = pop.root();
	example_with_ptr(pop);
    example_with_object(pop);
	pop.close();
	return 0;
}

// g++ -I/usr/local/include pmemobjcpp_string.cpp -lpmemobj -lpthread 